﻿using CMS6Tools.Management.Controls;
using CMS6Tools.Management.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;

namespace CMS6Tools.Management
{
    public partial class FeatureUsageMatrixForm : DockContent
    {
        public FeatureUsageMatrixForm()
        {
            InitializeComponent();
        }

        private void FeatureUsageMatrixForm_Load(object sender, EventArgs e)
        {
            StatisticsDataGridView.AutoGenerateColumns = false;
            DetailsDataGridView.AutoGenerateColumns = false;
            ProjectsDataGridView.AutoGenerateColumns = false;
            PasswordTextBox.Text = "{9C5DC4C8-3CA3-40BB-8AA4-D6E4092C4D56}";

            var checkboxHeaderCell = new DatagridViewCheckBoxHeaderCell();
            checkboxHeaderCell.HeaderText = string.Empty;
            ProjectsDataGridView.Columns[0].HeaderCell = checkboxHeaderCell;
            checkboxHeaderCell.OnCheckBoxClicked += checkboxHeaderCell_OnCheckBoxClicked;
        }

        async private void RunButton_Click(object sender, EventArgs e)
        {
            RunButton.Enabled = false;
            var selectedProjects = new List<ProjectModel>();
            var allProjectsInGridView = ProjectsDataGridView.DataSource as IEnumerable<ProjectModel>;
            if (allProjectsInGridView != null)
                selectedProjects = allProjectsInGridView.Where(a => a.Selected).ToList();
            if (!selectedProjects.Any())
            {
                MessageBox.Show("Please select at least 1 project in the grid view.");
                return;
            }

            await RunProjectsGetFeature(selectedProjects);

            MessageBox.Show("Done.");
            ResultTabControl.SelectedTab = StatisticsTabPage;

            RunButton.Enabled = true;
        }

        async Task RunProjectsGetFeature(List<ProjectModel> selectedProjects)
        {
            var oldWriter = Console.Out;
            Console.SetOut(new TextBoxWriter(LogTextBox));
            var logger = new global::Common.Logging.Simple.ConsoleOutLogger("Feature Management", global::Common.Logging.LogLevel.All, true, false, "hh:mm:ss.fff");

            var useDevSite = SiteTypeCheckBox.Checked;
            var featureUsageClientModelList = new List<FeatureUsageClientModel>();
            var successCount = 0;
            var failedCount = 0;
            var total = Projects.Count();
            var selectedCount = selectedProjects.Count;
            ProgressInfolabel.Text = string.Format("Total Projects: {0}, Selected: {3}, Success:{1}, Failed:{2}", total, successCount, failedCount, selectedCount);
            foreach (var projectInfo in selectedProjects)
            {
                var siteUrl = projectInfo.Url;
                try
                {
                    if (!string.IsNullOrEmpty(siteUrl))
                    {
                        var clientModel = new FeatureUsageClientModel
                        {
                            ClientName = projectInfo.Name,
                            Features = new List<FeatureUsageFeatureModel>(),
                            Identifier = projectInfo.Identifier,
                            URL = siteUrl,
                            License = projectInfo.License
                        };
                        logger.Info(string.Format("Getting feature matrix from {0}.", siteUrl));
                        var serviceURL = siteUrl.TrimEnd('/') + "/ws/FeatureWebService.asmx";
                        using (var featureService = new CMS6FeatureService.FeatureWebServiceSoapClient("FeatureWebServiceSoap", serviceURL))
                        {
                            var allFeatures = await featureService.FindAllFeatureModelsAsync(new CMS6FeatureService.AuthenticationSoapHeader
                            {
                                ClientIdentity = projectInfo.Identifier,
                                Password = projectInfo.ServicePassword,
                                UserName = "WebService"
                            });
                            clientModel.Features.AddRange(allFeatures.FindAllFeatureModelsResult.Select(a => new FeatureUsageFeatureModel
                            {
                                Name = a.Name,
                                DsiplayName = a.DisplayName,
                                Enabled = a.Actived, 
                            }));
                        }

                        featureUsageClientModelList.Add(clientModel);
                        logger.Info(string.Format("Got feature matrix from {0} successfully.", siteUrl));
                        successCount++;
                    }
                    else
                    {
                        failedCount++;
                    }
                }
                catch (Exception ex)
                {
                    failedCount++;
                    logger.Error(string.Format("Getting feature matrix from {0} failed.", siteUrl));
                }
                ProgressInfolabel.Text = string.Format("Total Projects: {0}, Selected: {3}, Success:{1}, Failed:{2}", total, successCount, failedCount, selectedCount);
            }

            Console.SetOut(oldWriter);

            BindStatisticsDataGridView(featureUsageClientModelList);
            BindDetailsDataGridView(featureUsageClientModelList);
        }

        private void BindStatisticsDataGridView(IEnumerable<FeatureUsageClientModel> clientModelList)
        {
            var dataSource = clientModelList.SelectMany(a => a.Features.Select(b => new
            {
                FeatureName = b.Name,
                FeatureDisplayName = b.DsiplayName,
                FeatureEnabled = b.Enabled,
                ClientName = a.ClientName,
                ClientUrl = a.URL,
                ClientIdentifier = a.Identifier,
                License = a.License
            }))
            .GroupBy(a => a.FeatureDisplayName)
            .Select(a => new
            {
                FeatureName = a.First().FeatureName,
                FeatureDisplayName = a.Key,
                EnabledCount = a.Count(b => b.FeatureEnabled),
                DisabledCount = a.Count(b => !b.FeatureEnabled)
            })
            .OrderBy(a => a.FeatureDisplayName)
            .ToList();
            StatisticsDataGridView.DataSource = dataSource;
        }

        private void BindDetailsDataGridView(IEnumerable<FeatureUsageClientModel> clientModelList)
        {
            var dataSource = clientModelList.SelectMany(a => a.Features.Select(b => new
            {
                FeatureName = b.Name,
                FeatureDisplayName = b.DsiplayName,
                Enabled = b.Enabled,
                ClientName = a.ClientName,
                Url = a.URL,
                ClientIdentifier = a.Identifier,
                License = a.License
            }))
            .OrderBy(a => a.ClientName).ThenBy(a => a.FeatureDisplayName)
            .ToList();
            DetailsDataGridView.DataSource = dataSource;
        }

        private void GetProjectsButton_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(VMCUrlTextBox.Text))
            {
                MessageBox.Show("VMC URL should not be EMPTY.");
                return;
            }
            if (string.IsNullOrEmpty(UserNameTextBox.Text))
            {
                MessageBox.Show("User Name should not be EMPTY.");
                return;
            }
            if (string.IsNullOrEmpty(PasswordTextBox.Text))
            {
                MessageBox.Show("Password should not be EMPTY.");
                return;
            }
            var oldWriter = Console.Out;
            Console.SetOut(new TextBoxWriter(LogTextBox));
            var logger = new global::Common.Logging.Simple.ConsoleOutLogger("Feature Management", global::Common.Logging.LogLevel.All, true, false, "hh:mm:ss.fff");

            logger.Info("Getting Project Information from VMC.");
            var projectInfoModelList = Enumerable.Empty<VMCProjectManagement.ProjectInfoModel>();
            var vmcServiceUrl = VMCUrlTextBox.Text.TrimEnd('/') + "/ProjectManagementWebService.asmx";
            var http = !vmcServiceUrl.StartsWith("https", StringComparison.InvariantCultureIgnoreCase);
            using (var service = new VMCProjectManagement.ProjectManagementWebServiceSoapClient(http ? "ProjectManagementWebServiceSoap" : "ProjectManagementWebServiceSoapHttps", vmcServiceUrl))
            {
                projectInfoModelList = service.GetAllProjectInfoList(new VMCProjectManagement.VCmcAuthenticationSoapHeader
                {
                    Password = PasswordTextBox.Text,
                    UserName = UserNameTextBox.Text
                });
            }
            logger.Info("Got Project Information from VMC.");

            var useDevSite = SiteTypeCheckBox.Checked;
            Projects = new List<ProjectModel>();
            var successCount = 0;
            var failedCount = 0;
            var total = projectInfoModelList.Count();
            ProgressInfolabel.Text = string.Format("Total Projects: {0}, Success:{1}, Failed:{2}", total, successCount, failedCount);
            foreach (var projectInfo in projectInfoModelList)
            {
                var siteUrl = useDevSite ? projectInfo.DevSiteUrl : projectInfo.LiveSiteUrl;

                var ProjectModel = new ProjectModel
                {
                    Name = projectInfo.Name,
                    Identifier = projectInfo.Identifier,
                    Url = siteUrl,
                    ServicePassword = projectInfo.ServicePassword,
                    Selected = true,
                    License = projectInfo.Type
                };

                Projects.Add(ProjectModel);
            }
            Projects = Projects.OrderBy(a => a.Name).ToList();
            ProjectsDataGridView.DataSource = Projects;

            Console.SetOut(oldWriter);
        }

        private void SearchProjectsButton_Click(object sender, EventArgs e)
        {
            if (Projects != null && Projects.Any() )
            {
                if (!string.IsNullOrEmpty(ProjectNameKeyTextBox.Text))
                {
                    var selectedProjects = Projects.Where(a => a.Name.ToLowerInvariant().Contains(ProjectNameKeyTextBox.Text.ToLowerInvariant())).ToList();

                    ProjectsDataGridView.DataSource = selectedProjects.ToList();
                }
                else
                {
                    ProjectsDataGridView.DataSource = Projects.ToList();
                }
            }
        }
        
        private void checkboxHeaderCell_OnCheckBoxClicked(int columnIndex, bool state)
        {
            var projects = ProjectsDataGridView.DataSource as IEnumerable<ProjectModel>;
            if (projects != null)
            {
                foreach (var project in projects)
                {
                    project.Selected = state;
                }
                ProjectsDataGridView.DataSource = projects.ToList();
            }
        }

        private List<ProjectModel> Projects { get; set; }

        class ProjectModel
        {
            public bool Selected { get; set; }
            public string Name { get; set; }
            public string Url { get; set; }
            public string Identifier { get; set; }
            public string ServicePassword { get; set; }
            public string License { get; set; }
        }

        private void ProjectNameKeyTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                SearchProjectsButton.PerformClick();
            }
        }

        private void ProjectsDataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            if (e.ColumnIndex == 0)
            {
                var allProjectsInGridView = ProjectsDataGridView.DataSource as List<ProjectModel>;
                if (allProjectsInGridView != null)
                {
                    //allProjectsInGridView[e.RowIndex].Selected = e.
                }
            }
            else
            {
                e.Cancel = true;
            }
        }
    }
}
